package com.mgg.gateway.filter;

import com.mgg.auth.AuthUser;
import com.mgg.gateway.service.rbac.RbacService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.stereotype.Component;

/**
 * 权限拦截器
 * @Author: lijun
 * @Date: 2018/9/6 15:11
 */
@Component
public class AuthFilter extends ZuulFilter{

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Autowired
    private RbacService rbacService;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication instanceof OAuth2Authentication) {
            return true;
        }
        return false;
    }

    @Override
    public Object run() {
        RequestContext requestContext = RequestContext.getCurrentContext();
        String header = requestContext.getRequest().getHeader("Authorization");
        if (header == null || !header.startsWith("Bearer ")) {
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        String token = StringUtils.substringAfter(header, "Bearer ");
        TokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
        OAuth2Authentication authentication = redisTokenStore.readAuthentication(token);
        if (!rbacService.hasPermission(requestContext.getRequest(), authentication)) {
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        String uid = ((AuthUser) authentication.getPrincipal()).getUserId();
        requestContext.addZuulRequestHeader("uid", uid);
        return null;
    }
}
